home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Cafe 3
/
Visual Cafe 3.ISO
/
Vcafe
/
JFC.bin
/
JScrollPane.java
< prev
next >
Wrap
Text File
|
1998-06-30
|
27KB
|
782 lines
/*
* @(#)JScrollPane.java 1.45 98/04/07
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
*/
package com.sun.java.swing;
import com.sun.java.swing.plaf.*;
import com.sun.java.swing.border.*;
import com.sun.java.accessibility.*;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Color;
import com.sun.java.swing.event.ChangeListener;
import com.sun.java.swing.event.ChangeEvent;
/**
* A specialized container that manages a viewport, optional
* vertical and horizontal scrollbars, and optional row and
* column heading viewports.
* <p>
* <TABLE ALIGN="RIGHT" BORDER="0">
* <TR>
* <TD ALIGN="CENTER">
* <P ALIGN="CENTER"><IMG SRC="doc-files/JScrollPane-1.gif" WIDTH="256" HEIGHT="248" ALIGN="BOTTOM" BORDER="0">
* </TD>
* </TR>
* </TABLE>
* The JViewPort provides a window, or "viewport" onto a data
* source -- for example, a text file. That data source is the
* "scrollable client" (aka data model) displayed by the
* JViewport view. A JScrollPane basically consists of JScrollBars, a JViewport,
* and the wiring between them, as shown in the diagram at right.
* <p>
* In addition to the scroll bars and viewport, a JScrollPane can have a
* column header and a row header. Each of these is a JViewport object that
* you specify with <code>setRowHeaderView</code>, and <code>setColumnHeaderView</code>.
* The column header viewport automatically scrolls left and right, tracking
* the left-right scrolling of the main viewport. (It never scrolls vertically,
* however.) The row header acts in a similar fashion.
* <p>
* By default, the corners are empty. You can put a component into a corner using
* <code>setCorner</code>, in case you there is some function or decoration you
* would like to add to the scroll pane. The size of corner components is
* entirely determined by the size of the headers and scroll bars that surround them.
* <p>
* To add a border around the main viewport, you can use <code>setViewportBorder</code>.
* (Of course, you can also add a border around the whole scroll pane using
* <code>setBorder</code>.)
* <p>
* For the keyboard keys used by this component in the standard Look and
* Feel (L&F) renditions, see the
* <a href="doc-files/Key-Index.html#JScrollPane">JScrollPane</a>
* key assignments.
* <p>
* Warning: serialized objects of this class will not be compatible with
* future swing releases. The current serialization support is appropriate
* for short term storage or RMI between Swing1.0 applications. It will
* not be possible to load serialized Swing1.0 objects with future releases
* of Swing. The JDK1.2 release of Swing will be the compatibility
* baseline for the serialized form of Swing objects.
*
* @see JScrollBar
* @see JViewport
* @see #setRowHeaderView
* @see #setColumnHeaderView
* @see #setCorner
* @see #setViewportBorder
* @beaninfo
* attribute: isContainer true
* description: A specialized container that manages a viewport, optional scrollbars and headings
*
* @version 1.45 04/07/98
* @author Hans Muller
*/
public class JScrollPane extends JComponent implements ScrollPaneConstants, Accessible
{
/** An array of constants that specify the corners */
protected final static String[] cornerKeywords = {
LOWER_LEFT_CORNER,
LOWER_RIGHT_CORNER,
UPPER_LEFT_CORNER,
UPPER_RIGHT_CORNER
};
private Border viewportBorder;
/**
* Create a JScrollPane that displays the contents of the specified
* component using the specified scrollbar policies. The scrollbar
* policies determine the circumstances under which the scrollbars
* are displayed:<ul>
* <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED
* <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER
* <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
* <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED
* <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
* <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS
* </ul>
* @param view the Component to display
* @param vsbPolicy an int specifying the vertical scrollbar policy
* @param hsbPolicy an int specifying the horizontal scrollbar policy
*/
public JScrollPane(Component view, int vsbPolicy, int hsbPolicy) {
/* The set methods that follow all delegate to the ScrollPaneUI
* object, so we initialize that first.
*/
updateUI();
setViewport(createViewport());
setViewportView(view);
setVerticalScrollBarPolicy(vsbPolicy);
setHorizontalScrollBarPolicy(hsbPolicy);
}
/**
* Create a JScrollPane that displays the contents of the specified
* component, where both horizontal and vertical scrollbars appear
* whenever the component's contents are larger than the view.
*
* @param view the Component to display
*/
public JScrollPane(Component view) {
this(view, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
/**
* Create an empty JScrollPane with specified scrollbar policies.
* The scrollbar policies determine the circumstances under which the
* scrollbars are displayed:<ul>
* <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED
* <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER
* <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
* <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED
* <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
* <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS
* </ul>
* </ul>
* @param vsbPolicy an int specifying the vertical scrollbar policy
* @param hsbPolicy an int specifying the horizontal scrollbar policy
*/
public JScrollPane(int vsbPolicy, int hsbPolicy) {
this(null, vsbPolicy, hsbPolicy);
}
/**
* Create an empty JScrollPane where both horizontal and vertical
* scrollbars appear when needed.
*/
public JScrollPane() {
this(null, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
/**
* Returns the L&F object that renders this component.
*
* @return the ScrollPaneUI object that renders this component
*/
public ScrollPaneUI getUI() {
return (ScrollPaneUI)ui;
}
/**
* Sets the L&F object that renders this component.
*
* @param ui the ScrollPaneUI L&F object
* @see UIDefaults#getUI
*/
public void setUI(ScrollPaneUI ui) {
super.setUI(ui);
}
/**
* Notification from the UIManager that the L&F has changed.
* Replaces the current UI object with the latest version from the
* UIManager.
*
* @see JComponent#updateUI
*/
public void updateUI()
{
// PENDING(hmuller) this mess should go away; bound properties.
/* The following properties are managed by the UI object. Since the'll
* disappear when we replace the UI object we cache them here. Note
* that one might set the UI to null and then later set it to a valid
* UI object, so we have to stash the property values until the UI
* is set to a non-null value.
*/
if (ui != null) {
JViewport viewport = getViewport();
JViewport rowHeader = getRowHeader();
JViewport columnHeader = getColumnHeader();
if (viewport != null) putClientProperty(VIEWPORT, viewport);
if (rowHeader != null) putClientProperty(ROW_HEADER, rowHeader);
if (columnHeader != null) putClientProperty(COLUMN_HEADER, columnHeader);
Integer vsbPolicy = new Integer(getVerticalScrollBarPolicy());
Integer hsbPolicy = new Integer(getHorizontalScrollBarPolicy());
putClientProperty(VERTICAL_SCROLLBAR_POLICY, vsbPolicy);
putClientProperty(HORIZONTAL_SCROLLBAR_POLICY, hsbPolicy);
for(int i = 0; i < cornerKeywords.length; i++) {
Component corner = getCorner(cornerKeywords[i]);
if (corner != null) putClientProperty(cornerKeywords[i], corner);
}
}
/* Reset the ScrollPaneUI property.
*/
setUI((ScrollPaneUI)UIManager.getUI(this));
/* Restored the non-null cached values for the ScrollPaneUI
* properties.
*/
if (ui != null) {
JViewport viewport = (JViewport)getClientProperty(VIEWPORT);
JViewport rowHeader = (JViewport)getClientProperty(ROW_HEADER);
JViewport columnHeader = (JViewport)getClientProperty(COLUMN_HEADER);
Integer vsbPolicy = (Integer)getClientProperty(VERTICAL_SCROLLBAR_POLICY);
Integer hsbPolicy = (Integer)getClientProperty(HORIZONTAL_SCROLLBAR_POLICY);
if (vsbPolicy != null) { setVerticalScrollBarPolicy(vsbPolicy.intValue()); }
if (hsbPolicy != null) { setHorizontalScrollBarPolicy(hsbPolicy.intValue()); }
if (viewport != null) { setViewport(viewport); }
if (rowHeader != null) { setRowHeader(rowHeader); }
if (columnHeader != null) { setColumnHeader(columnHeader); }
for(int i = 0; i < cornerKeywords.length; i++) {
Component corner = (Component)getClientProperty(cornerKeywords[i]);
if (corner != null) {
setCorner(cornerKeywords[i], corner);
} else {
// PENDING(klobad) verify with Hans for this solution
setCorner(cornerKeywords[i], new JPanel() {
public void paint(Graphics g) {
Color controlColor = UIManager.getColor("control");
g.setColor(controlColor);
g.fillRect(0, 0, _bounds.width, _bounds.height);
}
public boolean isOpaque() { return true; }
});
}
}
}
}
/**
* Returns the name of the L&F class that renders this component.
*
* @return "ScrollPaneUI"
* @see JComponent#getUIClassID
* @see UIDefaults#getUI
*/
public String getUIClassID() {
return "ScrollPaneUI";
}
/**
* Returns the vertical scrollbar policy.
*
* @return an int giving the policy
* @see #setVerticalScrollBarPolicy
*/
public int getVerticalScrollBarPolicy() {
return getUI().getVerticalScrollBarPolicy();
}
/*
* Determines when the vertical scrollbar appears in the scrollpane, where
* the options are:<ul>
* <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED
* <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER
* <li>ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS
* </ul>
*
* @beaninfo
* preferred: true
* description: The scrollpane scrollbar policy
* enum: VERTICAL_SCROLLBAR_AS_NEEDED JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
* VERTICAL_SCROLLBAR_NEVER JScrollPane.VERTICAL_SCROLLBAR_NEVER
* VERTICAL_SCROLLBAR_ALWAYS JScrollPane.VERTICAL_SCROLLBAR_ALWAYS
*/
public void setVerticalScrollBarPolicy(int x) {
if (x != getVerticalScrollBarPolicy()) {
getUI().setVerticalScrollBarPolicy(x);
invalidate();
}
}
/**
* Returns the horizontal scrollbar policy.
*
* @return an int giving the policy
* @see #setHorizontalScrollBarPolicy
*/
public int getHorizontalScrollBarPolicy() {
return getUI().getHorizontalScrollBarPolicy();
}
/*
* Determines when the horizontal scrollbar appears in the scrollpane, where
* the options are:<ul>
* <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED
* <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER
* <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS
* </ul>
*
* @beaninfo
* preferred: true
* description: The scrollpane scrollbar policy
* enum: HORIZONTAL_SCROLLBAR_AS_NEEDED JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
* HORIZONTAL_SCROLLBAR_NEVER JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
* HORIZONTAL_SCROLLBAR_ALWAYS JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS
*/
public void setHorizontalScrollBarPolicy(int x) {
if (x != getHorizontalScrollBarPolicy()) {
getUI().setHorizontalScrollBarPolicy(x);
invalidate();
}
}
/**
* Returns the value of the viewportBorder property.
*
* @return the Border object that surrounds the viewport
* @see #setViewportBorder
*/
public Border getViewportBorder() {
return viewportBorder;
}
/**
* Add a border around the viewport. Note that the border isn't
* set on the viewport directly, JViewport doesn't support the
* JComponent border property. Similarly setting the JScrollPanes
* viewport doesn't effect the viewportBorder property.
* <p>
* The default value of this property is computed by the look
* and feel implementation.
* <p>
* This is a JavaBeans bound property.
*
* @see #getViewportBorder
* @see #setViewport
*
* @beaninfo
* preferred: true
* bound: true
* description: The border around the viewport.
*/
public void setViewportBorder(Border viewportBorder) {
Border oldValue = this.viewportBorder;
this.viewportBorder = viewportBorder;
firePropertyChange("viewportBorder", oldValue, viewportBorder);
}
/**
* By default JScrollPane creates scrollbars that are instances
* of this class. Scrollbar overrides the getUnitIncrement
* and getBlockIncrement methods so that, if the viewports view is
* a Scrollable, the view is asked to compute these values.
* <p>
* Warning: serialized objects of this class will not be compatible with
* future swing releases. The current serialization support is appropriate
* for short term storage or RMI between Swing1.0 applications. It will
* not be possible to load serialized Swing1.0 objects with future releases
* of Swing. The JDK1.2 release of Swing will be the compatibility
* baseline for the serialized form of Swing objects.
*
* @see Scrollable
* @see JScrollPane#createVerticalScrollBar
* @see JScrollPane#createHorizontalScrollBar
*/
protected class ScrollBar extends JScrollBar
{
/**
* Create a scrollbar with the specified orientation, where the options
* are:<ul>
* <li>ScrollPaneConstants.VERTICAL_SCROLLBAR
* <li>ScrollPaneConstants.HORIZONTAL_SCROLLBAR
* </ul>
*
* @param orientation an int specifying the orientation
*/
public ScrollBar(int orientation) {
super(orientation);
}
/**
* If the viewports view is a Scrollable then ask the view
* to compute the unit increment. Otherwise return
* super.getUnitIncrement().
*
* @see Scrollable#getScrollableUnitIncrement
*/
public int getUnitIncrement(int direction) {
JViewport vp = getViewport();
if ((vp != null) && (vp.getView() instanceof Scrollable)) {
Scrollable view = (Scrollable)(vp.getView());
Rectangle vr = vp.getViewRect();
return view.getScrollableUnitIncrement(vr, getOrientation(), direction);
}
else {
return super.getUnitIncrement(direction);
}
}
/**
* If the viewports view is a Scrollable then ask the
* view to compute the block increment. Otherwise
* the blockIncrement equals the viewports width
* or height. If there's no viewport reuurn
* super.getBlockIncrement().
*
* @see Scrollable#getScrollableBlockIncrement
*/
public int getBlockIncrement(int direction) {
JViewport vp = getViewport();
if (vp == null) {
return super.getBlockIncrement(direction);
}
else if (vp.getView() instanceof Scrollable) {
Scrollable view = (Scrollable)(vp.getView());
Rectangle vr = vp.getViewRect();
return view.getScrollableBlockIncrement(vr, getOrientation(), direction);
}
else if (getOrientation() == VERTICAL) {
return vp.getExtentSize().width;
}
else {
return vp.getExtentSize().height;
}
}
}
/**
* Used by ScrollPaneUI implementations to create the horizontal
* scrollbar. Returns a JScrollPane.ScrollBar by default. Subclasses
* may override this method to force ScrollPaneUI implementations to
* use a JScrollBar subclass.
*
* @return a JScrollBar with a horizontal orientation
* @see JScrollBar
*/
public JScrollBar createHorizontalScrollBar() {
return new ScrollBar(JScrollBar.HORIZONTAL);
}
/**
* Used by ScrollPaneUI implementations to create the vertical
* scrollbar. Returns a JScrollPane.ScrollBar by default. Subclasses
* may override this method to force ScrollPaneUI implementations to
* use a JScrollBar subclass.
*
* @return a JScrollBar with a vertical orientation
* @see JScrollBar
*/
public JScrollBar createVerticalScrollBar() {
return new ScrollBar(JScrollBar.VERTICAL);
}
/**
* Returns the horizontal scroll bar currently in use.
*
* @return the JScrollBar currently used for horizontal scrolling
* @see ScrollBar
*/
public JScrollBar getHorizontalScrollBar() {
return getUI().getHorizontalScrollBar();
}
/**
* Returns the vertical scroll bar currently in use.
*
* @return the JScrollBar currently used for vertical scrolling
* @see ScrollBar
*/
public JScrollBar getVerticalScrollBar() {
return getUI().getVerticalScrollBar();
}
/**
* Returns a new JViewport by default. Used to create the
* viewport (as needed) in <code>setViewportView</code>,
* <code>setRowHeaderView</code>, and <code>setColumnHeaderView</code>.
* Subclasses may override this method to return a subclass of JViewport.
*
* @return a JViewport
*/
protected JViewport createViewport() {
return new JViewport();
}
/**
* Returns the current JViewport.
*
* @return the JViewport currently in use
*/
public JViewport getViewport() {
return getUI().getViewport();
}
/**
* Sets the current JViewport.
*
* @return the JViewport to use
*/
public void setViewport(JViewport x) {
if (x != getViewport()) {
getUI().setViewport(x);
invalidate();
if (accessibleContext != null) {
((AccessibleJScrollPane)accessibleContext).resetViewPort();
}
}
}
/**
* Creates a viewport if neccessary and then sets its view.
*
* @param view the Component to view
*/
public void setViewportView(Component view) {
if (getViewport() == null) {
setViewport(createViewport());
}
getViewport().setView(view);
}
/**
* Returns the row-header viewport.
*
* @return the JViewport for the row header
*/
public JViewport getRowHeader() {
return getUI().getRowHeader();
}
/**
* Sets a row-header viewport.
*
* @param x the JViewport to use for a row header
* @beaninfo
* preferred: true
* description: The header viewport.
*/
public void setRowHeader(JViewport x) {
if (x != getRowHeader()) {
getUI().setRowHeader(x);
invalidate();
}
}
/**
* Creates a row-header viewport if neccessary and then sets
* its view.
*
* @param view the Component to display as the row header
*/
public void setRowHeaderView(Component view) {
if (getRowHeader() == null) {
setRowHeader(createViewport());
}
getRowHeader().setView(view);
}
/**
* Returns the column-header viewport.
*
* @return the JViewport for the column header
*/
public JViewport getColumnHeader() {
return getUI().getColumnHeader();
}
/**
* Sets a column-header viewport
*
* @param x the JViewport to use for the column header
* @beaninfo
* preferred: true
* description: The column viewport.
*/
public void setColumnHeader(JViewport x) {
if (x != getColumnHeader()) {
getUI().setColumnHeader(x);
invalidate();
}
}
/**
* Creates a column-header viewport if neccessary and then sets
* its view.
*
* @param view the Component to display as the column header
*/
public void setColumnHeaderView(Component view) {
if (getColumnHeader() == null) {
setColumnHeader(createViewport());
}
getColumnHeader().setView(view);
}
/**
* Returns the _________________,
* where the options for the key are:<ul>
* <li>ScrollPaneConstants.LOWER_LEFT_CORNER
* <li>ScrollPaneConstants.LOWER_RIGHT_CORNER
* <li>ScrollPaneConstants.UPPER_LEFT_CORNER
* <li>ScrollPaneConstants.UPPER_RIGHT_CORNER
* </ul>
* @param key a String specifying the corner
* @return the Component _________________
*/
public Component getCorner(String key) {
return getUI().getCorner(key);
}
/**
* Sets the _________________,
* where the options for the key are:<ul>
* <li>ScrollPaneConstants.LOWER_LEFT_CORNER
* <li>ScrollPaneConstants.LOWER_RIGHT_CORNER
* <li>ScrollPaneConstants.UPPER_LEFT_CORNER
* <li>ScrollPaneConstants.UPPER_RIGHT_CORNER
* </ul>
* @param key a String specifying the corner
* @param x the Component _________________
*/
public void setCorner(String key, Component x) {
if (x != getCorner(key)) {
getUI().setCorner(key, x);
invalidate();
}
}
/**
* Returns true if this component paints every pixel
* in its range. (In other words, it does not have a transparent
* background or foreground.)
*
* @return The value of the opaque property
* @see JComponent#isOpaque
*/
public boolean isOpaque() {
JViewport viewport;
Component view;
if( (viewport = getViewport()) != null &&
((view = viewport.getView()) != null) &&
((view instanceof JComponent) && ((JComponent)view).isOpaque())) {
if(((JComponent)view).getWidth() >= viewport.getWidth() &&
((JComponent)view).getHeight() >= viewport.getHeight())
return true;
}
return false;
}
/**
* Calls to revalidate() any descendant of this JScrollPane, e.g.
* the viewports view, will cause a request to be queued that
* will validate this JScrollPane and all its descendants.
*
* @return true
* @see revalidate
* @see java.awt.Component#invalidate
* @see java.awt.Container#validate
*/
public boolean isValidateRoot() {
return true;
}
/////////////////
// Accessibility support
////////////////
/**
* Get the AccessibleContext associated with this JComponent
*
* @return the AccessibleContext of this JComponent
*/
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleJScrollPane();
}
return accessibleContext;
}
/**
* The class used to obtain the accessible role for this object.
* <p>
* Warning: serialized objects of this class will not be compatible with
* future swing releases. The current serialization support is appropriate
* for short term storage or RMI between Swing1.0 applications. It will
* not be possible to load serialized Swing1.0 objects with future releases
* of Swing. The JDK1.2 release of Swing will be the compatibility
* baseline for the serialized form of Swing objects.
*/
protected class AccessibleJScrollPane extends AccessibleJComponent
implements ChangeListener {
protected JViewport viewPort = null;
public void resetViewPort() {
viewPort.removeChangeListener(this);
viewPort = JScrollPane.this.getViewport();
viewPort.addChangeListener(this);
}
/**
* Constructor to set up listener on viewport.
*/
public AccessibleJScrollPane() {
super();
if (viewPort == null) {
viewPort = JScrollPane.this.getViewport();
}
viewPort.addChangeListener(this);
}
/**
* Get the role of this object.
*
* @return an instance of AccessibleRole describing the role of the
* object
* @see AccessibleRole
*/
public AccessibleRole getAccessibleRole() {
return AccessibleRole.SCROLL_PANE;
}
/**
* Supports the change listener interface and fires property change
*/
public void stateChanged(ChangeEvent e) {
AccessibleContext ac = ((Accessible)JScrollPane.this).getAccessibleContext();
if (ac != null) {
ac.firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, new Boolean(false), new Boolean(true));
}
}
}
}